package com.george.reversing;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.nio.ByteBuffer;

import com.george.reversing.util.Camera2Proxy;

import android.graphics.Bitmap;
import android.graphics.ImageFormat;
import android.graphics.SurfaceTexture;
import android.media.Image;
import android.media.ImageReader;
import android.os.Bundle;
import android.os.Environment;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.util.Size;
import android.view.LayoutInflater;
import android.view.TextureView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;

public class CameraFragment extends Fragment implements View.OnClickListener {

    private static final String TAG = "CameraFragment";

    private ImageView mCloseIv;
    private ImageView mSwitchCameraIv;
    private ImageView mTakePictureIv;
    private Camera2View mCameraView;

    private Camera2Proxy mCameraProxy;
    
    public static final int YUV420P = 0;
    public static final int YUV420SP = 1;
    public static final int NV21 = 2;

    private final TextureView.SurfaceTextureListener mSurfaceTextureListener
            = new TextureView.SurfaceTextureListener() {

        @Override
        public void onSurfaceTextureAvailable(SurfaceTexture texture, int width, int height) {
            mCameraProxy.openCamera();
            mCameraProxy.setPreviewSurface(texture);
            // 根据相机预览设置View大小，避免显示变形
            Size previewSize = mCameraProxy.getPreviewSize();
            mCameraView.setAspectRatio(previewSize.getHeight(), previewSize.getWidth());
        }

        @Override
        public void onSurfaceTextureSizeChanged(SurfaceTexture texture, int width, int height) {
        }

        @Override
        public boolean onSurfaceTextureDestroyed(SurfaceTexture texture) {
        	
            return true;
        }

        @Override
        public void onSurfaceTextureUpdated(SurfaceTexture texture) {
        }

    };

    @Override
    public View onCreateView( LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_camera2, null);
        initView(rootView);
        return rootView;
    }

    private void initView(View rootView) {
//        mCloseIv = (ImageView) rootView.findViewById(R.id.toolbar_close_iv);
//        mSwitchCameraIv = (ImageView) rootView.findViewById(R.id.toolbar_switch_iv);
//        mTakePictureIv = (ImageView) rootView.findViewById(R.id.take_picture_iv);
        mCameraView = (Camera2View) rootView.findViewById(R.id.camera_view);
        mCameraProxy = mCameraView.getCameraProxy();

//        mCloseIv.setOnClickListener(this);
//        mSwitchCameraIv.setOnClickListener(this);
//        mTakePictureIv.setOnClickListener(this);
        mCameraProxy.setImageAvailableListener(mOnImageAvailableListener);
    }

    @Override
    public void onResume() {
        super.onResume();
        if (mCameraView.isAvailable()) {
            mCameraProxy.openCamera();
        } else {
            mCameraView.setSurfaceTextureListener(mSurfaceTextureListener);
        }
    }

    @Override
    public void onPause() {
        super.onPause();
        mCameraProxy.releaseCamera();
    }

    @Override
    public void onClick(View v) {
//        switch (v.getId()) {
//            case R.id.toolbar_close_iv:
//                getActivity().finish();
//                break;
//            case R.id.toolbar_switch_iv:
//                mCameraProxy.switchCamera();
//                break;
//            case R.id.take_picture_iv:
//                mIsShutter = true;
//                break;
//        }
    }

    private byte[] mYuvBytes;
    private boolean mIsShutter;

    private ImageReader.OnImageAvailableListener mOnImageAvailableListener
            = new ImageReader.OnImageAvailableListener() {

        @Override
        public void onImageAvailable(ImageReader reader) {
        	Log.e(TAG, "----");
            Image image = reader.acquireLatestImage();
            if (image == null) {
            	return;
            }
//            int imageWidth = image.getWidth();
//            int imageHeight = image.getHeight();
//            Log.e(TAG, "---imageWidth ="+imageWidth+" imageHeight="+imageHeight);
//            byte[] data68 = getBytesFromImageAsType(image,YUV420P);
//
////            if(time==5) {
//               int rgb[] = decodeYUV420SP(data68, imageWidth, imageHeight);
//                Bitmap bitmap2 = Bitmap.createBitmap(rgb, 0, imageWidth,
//                        imageWidth, imageHeight,
//                        android.graphics.Bitmap.Config.ARGB_8888);
//                try {
//                    File newFile = new File(Environment.getExternalStorageDirectory(), "345.png");
//                    BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(newFile));
//                    bitmap2.compress(Bitmap.CompressFormat.PNG, 100, bos);
//                    bos.flush();
//                    bos.close();
//                    bitmap2.recycle();
//                } catch (Exception e) {
//                	e.printStackTrace();
//                }
////            }

            image.close();
//            int width = mCameraProxy.getPreviewSize().getWidth();
//            int height = mCameraProxy.getPreviewSize().getHeight();
//            if (mYuvBytes == null) {
//                // YUV420 大小总是 width * height * 3 / 2
//                mYuvBytes = new byte[width * height * 3 / 2];
//            }
//
//            // YUV_420_888
//            Image.Plane[] planes = image.getPlanes();
//
//            // Y通道，对应planes[0]
//            // Y size = width * height
//            // yBuffer.remaining() = width * height;
//            // pixelStride = 1
//            ByteBuffer yBuffer = planes[0].getBuffer();
//            int yLen = width * height;
//            yBuffer.get(mYuvBytes, 0, yLen);
//            // U通道，对应planes[1]
//            // U size = width * height / 4;
//            // uBuffer.remaining() = width * height / 2;
//            // pixelStride = 2
//            ByteBuffer uBuffer = planes[1].getBuffer();
//            int pixelStride = planes[1].getPixelStride(); // pixelStride = 2
//            for (int i = 0; i < uBuffer.remaining(); i+=pixelStride) {
//                mYuvBytes[yLen++] = uBuffer.get(i);
//            }
//            // V通道，对应planes[2]
//            // V size = width * height / 4;
//            // vBuffer.remaining() = width * height / 2;
//            // pixelStride = 2
//            ByteBuffer vBuffer = planes[2].getBuffer();
//            pixelStride = planes[2].getPixelStride(); // pixelStride = 2
//            for (int i = 0; i < vBuffer.remaining(); i+=pixelStride) {
//                mYuvBytes[yLen++] = vBuffer.get(i);
//            }
//
//            if (mIsShutter) {
//                mIsShutter = false;
//
//                // save yuv data
//                String yuvPath = FileUtil.SAVE_DIR + System.currentTimeMillis() + ".yuv";
//                FileUtil.saveBytes(mYuvBytes, yuvPath);
//
//                // save bitmap data
//                String jpgPath = yuvPath.replace(".yuv", ".jpg");
//                Bitmap bitmap = ColorConvertUtil.yuv420pToBitmap(mYuvBytes, width, height);
//                FileUtil.saveBitmap(bitmap, jpgPath);
//            }

            // 一定不能忘记close
           
        }
    };
    
    public static byte[] getBytesFromImageAsType(Image image, int type) {
        try {
            //获取源数据，如果是YUV格式的数据planes.length = 3
            //plane[i]里面的实际数据可能存在byte[].length <= capacity (缓冲区总大小)
            final Image.Plane[] planes = image.getPlanes();

            //数据有效宽度，一般的，图片width <= rowStride，这也是导致byte[].length <= capacity的原因
            // 所以我们只取width部分
            int width = image.getWidth();
            int height = image.getHeight();

            //此处用来装填最终的YUV数据，需要1.5倍的图片大小，因为Y U V 比例为 4:1:1
            byte[] yuvBytes = new byte[width * height * ImageFormat.getBitsPerPixel(ImageFormat.YUV_420_888) / 8];
            //目标数组的装填到的位置
            int dstIndex = 0;

            //临时存储uv数据的
            byte uBytes[] = new byte[width * height / 4];
            byte vBytes[] = new byte[width * height / 4];
            int uIndex = 0;
            int vIndex = 0;

            int pixelsStride, rowStride;
            for (int i = 0; i < planes.length; i++) {
                pixelsStride = planes[i].getPixelStride();
                rowStride = planes[i].getRowStride();

                ByteBuffer buffer = planes[i].getBuffer();

                //如果pixelsStride==2，一般的Y的buffer长度=640*480，UV的长度=640*480/2-1
                //源数据的索引，y的数据是byte中连续的，u的数据是v向左移以为生成的，两者都是偶数位为有效数据
                byte[] bytes = new byte[buffer.capacity()];
                buffer.get(bytes);

                int srcIndex = 0;
                if (i == 0) {
                    //直接取出来所有Y的有效区域，也可以存储成一个临时的bytes，到下一步再copy
                    for (int j = 0; j < height; j++) {
                        System.arraycopy(bytes, srcIndex, yuvBytes, dstIndex, width);
                        srcIndex += rowStride;
                        dstIndex += width;
                    }
                } else if (i == 1) {
                    //根据pixelsStride取相应的数据
                    for (int j = 0; j < height / 2; j++) {
                        for (int k = 0; k < width / 2; k++) {
                            uBytes[uIndex++] = bytes[srcIndex];
                            srcIndex += pixelsStride;
                        }
                        if (pixelsStride == 2) {
                            srcIndex += rowStride - width;
                        } else if (pixelsStride == 1) {
                            srcIndex += rowStride - width / 2;
                        }
                    }
                } else if (i == 2) {
                    //根据pixelsStride取相应的数据
                    for (int j = 0; j < height / 2; j++) {
                        for (int k = 0; k < width / 2; k++) {
                            vBytes[vIndex++] = bytes[srcIndex];
                            srcIndex += pixelsStride;
                        }
                        if (pixelsStride == 2) {
                            srcIndex += rowStride - width;
                        } else if (pixelsStride == 1) {
                            srcIndex += rowStride - width / 2;
                        }
                    }
                }
            }

         //   image.close();

            //根据要求的结果类型进行填充
            switch (type) {
                case YUV420P:
                    System.arraycopy(uBytes, 0, yuvBytes, dstIndex, uBytes.length);
                    System.arraycopy(vBytes, 0, yuvBytes, dstIndex + uBytes.length, vBytes.length);
                    break;
                case YUV420SP:
                    for (int i = 0; i < vBytes.length; i++) {
                        yuvBytes[dstIndex++] = uBytes[i];
                        yuvBytes[dstIndex++] = vBytes[i];
                    }
                    break;
                case NV21:
                    for (int i = 0; i < vBytes.length; i++) {
                        yuvBytes[dstIndex++] = vBytes[i];
                        yuvBytes[dstIndex++] = uBytes[i];
                    }
                    break;
            }
            return yuvBytes;
        } catch (final Exception e) {
            if (image != null) {
                image.close();
            }
            Log.i(TAG, e.toString());
        }
        return null;
    }
    
    public static int[] decodeYUV420SP(byte[] yuv420sp, int width, int height)
    {
        final int frameSize = width * height;
        int rgb[] = new int[frameSize];
        for (int j = 0, yp = 0; j < height; j++) {
            int uvp = frameSize + (j >> 1) * width, u = 0, v = 0;
            for (int i = 0; i < width; i++, yp++) {
                int y = (0xff & ((int) yuv420sp[yp])) - 16;
                if (y < 0)
                    y = 0;
                if ((i & 1) == 0) {
                    v = (0xff & yuv420sp[uvp++]) - 128;
                    u = (0xff & yuv420sp[uvp++]) - 128;
                }
                int y1192 = 1192 * y;
                int r = (y1192 + 1634 * v);
                int g = (y1192 - 833 * v - 400 * u);
                int b = (y1192 + 2066 * u);
                if (r < 0)
                    r = 0;
                else if (r > 262143)
                    r = 262143;
                if (g < 0)
                    g = 0;
                else if (g > 262143)
                    g = 262143;
                if (b < 0)
                    b = 0;
                else if (b > 262143)
                    b = 262143;
                rgb[yp] = 0xff000000 | ((r << 6) & 0xff0000)
                        | ((g >> 2) & 0xff00) | ((b >> 10) & 0xff);
            }
        }
        return rgb;
    }
}
